/****************************************************** 
 *  Copyright 2018 IBM Corporation 
 *  Licensed under the Apache License, Version 2.0 (the "License"); 
 *  you may not use this file except in compliance with the License. 
 *  You may obtain a copy of the License at 
 *  http://www.apache.org/licenses/LICENSE-2.0 
 *  Unless required by applicable law or agreed to in writing, software 
 *  distributed under the License is distributed on an "AS IS" BASIS, 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 *  See the License for the specific language governing permissions and 
 *  limitations under the License.
 */
package com.hyperledger.fabric.sdk3;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.security.PrivateKey;
import java.util.Collection;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.io.IOUtils;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.hyperledger.fabric.sdk.Channel;
import org.hyperledger.fabric.sdk.Enrollment;
import org.hyperledger.fabric.sdk.EventHub;
import org.hyperledger.fabric.sdk.Orderer;
import org.hyperledger.fabric.sdk.Peer;
import org.hyperledger.fabric.sdk.ProposalResponse;
import org.hyperledger.fabric.sdk3.Config;
import org.hyperledger.fabric.sdk3.Util;
import org.hyperledger.fabric.sdk3.client.CAClient;
import org.hyperledger.fabric.sdk3.client.ChannelClient;
import org.hyperledger.fabric.sdk3.client.FabricClient;
import org.hyperledger.fabric.sdk3.user.UserContext;
import org.hyperledger.fabric_ca.sdk.EnrollmentRequest;
import org.hyperledger.fabric_ca.sdk.HFCAClient;
import org.hyperledger.fabric_ca.sdk.exception.EnrollmentException;
import org.hyperledger.fabric_ca.sdk.exception.InvalidArgumentException;

/**
 * <p>
 * From https://blog.csdn.net/qq_27348837/article/details/95489720
 * 
 * @author Balaji Kadambi
 *
 */

public class QueryChaincode {

	private static final byte[] EXPECTED_EVENT_DATA = "!".getBytes(UTF_8);

	private static final String EXPECTED_EVENT_NAME = "event";

	public static void main(String args[]) {
		try {
			Util.cleanUp();
			UserContext adminUser = new UserContext();
			adminUser.setName(Config.ADMIN);
			adminUser.setAffiliation(Config.ORG1);
			adminUser.setMspId(Config.ORG1_MSP);
			File f = new File(Config.CA1_TLSFILE);
			String certficate = new String(IOUtils.toByteArray(new FileInputStream(f)), "UTF-8");
			Properties properties = new Properties();
			properties.put("pemBytes", certficate.getBytes());
			properties.setProperty("pemFile", f.getAbsolutePath());
			properties.setProperty("allowAllHostNames", "true");
			CAClient caclient = new CAClient(Config.CA1NAME, Config.CA_ORG1_URL, properties);
			caclient.setAdminUserContext(adminUser);
			adminUser = caclient.enrollAdminUserTLS("admin", "adminpw");
			FabricClient fabClient = new FabricClient(adminUser);
			ChannelClient channelClient = fabClient.createChannelClient(Config.CHANNEL_NAME);
			Channel channel = channelClient.getChannel();
			Properties properties1 = Util.gete2ePro("peer", Config.ORG1_PEER_0);
			Peer peer = fabClient.getInstance().newPeer(Config.ORG1_PEER_0, Config.ORG1_PEER_0_URL, properties1);

			EventHub eventHub = fabClient.getInstance().newEventHub("eventhub01", Config.grpc + Config.baseUrl + ":7053");
			Properties orderPro = Util.gete2ePro("orderer", Config.ORDERER_NAME);
			Orderer orderer = fabClient.getInstance().newOrderer(Config.ORDERER_NAME, Config.ORDERER_URL, orderPro);
			channel.addPeer(peer);
			channel.addOrderer(orderer);
			channel.initialize();
			Logger.getLogger(QueryChaincode.class.getName()).log(Level.INFO, "Querying   ...");
			// queryAll
			Collection<ProposalResponse> responsesQuery = channelClient.queryByChainCode("netcon", "queryAll",
			      new String[] { "a" });
			// query
			// Collection<ProposalResponse> responsesQuery = channelClient.queryByChainCode("mycc", "query", new String[] {"a"});
			for (ProposalResponse pres : responsesQuery) {
				String stringResponse = new String(pres.getChaincodeActionResponsePayload());
				Logger.getLogger(QueryChaincode.class.getName()).log(Level.INFO, stringResponse);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static HFCAClient enableTLS(HFCAClient hfcaclient, String uesrName, String userpasswd, String orgName,
	      String caHsotIp) {
		final EnrollmentRequest enrollmentRequestTLS = new EnrollmentRequest();
		enrollmentRequestTLS.addHost(caHsotIp);
		enrollmentRequestTLS.setProfile("tls");
		try {
			final Enrollment enroll = hfcaclient.enroll(uesrName, userpasswd, enrollmentRequestTLS);
			final String tlsCertPEM = enroll.getCert();
			final String tlsKeyPEM = getPEMStringFromPrivateKey(enroll.getKey());
			final Properties tlsProperties = new Properties();
			tlsProperties.put("clientKeyBytes", tlsKeyPEM.getBytes(UTF_8));
			tlsProperties.put("clientCertBytes", tlsCertPEM.getBytes(UTF_8));

		} catch (EnrollmentException | InvalidArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return hfcaclient;

	}

	static String getPEMStringFromPrivateKey(PrivateKey privateKey) throws IOException {
		StringWriter pemStrWriter = new StringWriter();
		JcaPEMWriter pemWriter = new JcaPEMWriter(pemStrWriter);

		pemWriter.writeObject(privateKey);

		pemWriter.close();

		return pemStrWriter.toString();
	}

}
